<template>
  <el-dialog
    :title="formData.slaveChipInterfaceName + '接口设置'"
    :visible.sync="dialogVisible"
    width="848px"
    @closed="handleClose"
  >
    <el-form ref="formData" class="myForm" :model="formData" label-suffix="：" :rules="rules" label-position="top">
      <el-row :gutter="20">
        <el-col :span="8">
          <el-form-item class="label-position-right1" label="接口类型" prop="slaveChipInterfaceTypeName">
            <el-select v-model="formData.slaveChipInterfaceTypeName" filterable class="mySelect">
              <el-option
                v-for="item in formData.interfaceTypeOptionList"
                :key="item.value"
                :label="item.label"
                :value="item.value + ''"
              ></el-option>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item
            v-if="resourceNameOptionList.length > 0"
            class="label-position-right"
            label="资源"
            prop="masterChipResourceName"
          >
            <el-select
              v-model="formData.masterChipResourceName"
              filterable
              class="mySelect"
              @change="handleChange"
            >
              <el-option
                v-for="item in resourceNameOptionList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <el-divider v-if="pinList.length > 0" content-position="left" class="title">引脚配置</el-divider>
      <el-row>
        <el-col v-for="pin in pinList" :key="pin.masterChipInterfacePinFunctionId" class="pinBox">
          <el-form-item :label="pin.masterChipPinName" :prop="pin.masterChipPinName">
            <el-select
              v-model="formData[pin.masterChipPinName]"
              style="width: 245px"
              @change="handleChangePin($event, pin)"
            >
              <el-option
                v-for="row in pin.pinCodeOptionList"
                :key="row.value"
                :label="row.label"
                :value="row.value"
                :disabled="isDisabled(row.value)"
              ></el-option>
            </el-select>
          </el-form-item>
          <el-row :gutter="20">
            <el-form :ref="'pinForm'" :model="pin.parameterFormData" label-suffix="：" :rules="pin.rules">
              <el-col v-for="pinParameter in pin.parameterList" :key="pinParameter.symbol" :span="8">
                <formField
                  :size="'mini'"
                  :item="pinParameter"
                  :form-data="pin.parameterFormData"
                  @change="getRealPinList(pin)"
                />
              </el-col>
            </el-form>
          </el-row>
        </el-col>
      </el-row>
      <el-divider v-if="parameterList.length > 0" content-position="left" class="title">参数配置</el-divider>
      <el-row :gutter="20">
        <el-col v-for="item in parameterList" :key="item.symbol" :span="8">
          <formField :item="item" :form-data="formData" @change="getRealParameterList" />
        </el-col>
      </el-row>
    </el-form>
    <div slot="footer" style="display: block; text-align: center">
      <el-button @click="handelCancle">取消</el-button>
      <el-button type="primary" @click="handelConfirm">保存配置</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { getStrLength } from '@/utils/index'
import { getPinAndParameterData, getPinParameter, getPinCodeOptionData } from '@/api/project-management'
import { multipleDependencyRuleCheck, dependencyRuleCheck, ruleCheck } from '@/api/rule-management'
import formField from './formField.vue'
import defaultSettings from '@/settings'
import { generateUUID, postMessage, receivedMessage } from '@/utils/index'
export default {
  components: { formField },
  props: {
    masterChipId: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      dialogVisible: false,
      formData: { masterChipResourceName: '' },
      rules: {
        slaveChipInterfaceTypeName: [{ required: true, message: '请选择接口类型', trigger: ['blur', 'change'] }],
        masterChipResourceName: [{ required: true, message: '请选择资源', trigger: ['blur', 'change'] }]
      },
      // resourceNameOptionList: [],
      parameterList: [],
      pinList: [],
      usedPinCodeList: [],
      getPinAndParameterDataRequestId: generateUUID(),
      getPinParameterRequestId: generateUUID(),
      getPinCodeOptionDataRequestId: generateUUID(),
      dependencyRuleCheckRequestId: generateUUID(),
      multipleDependencyRuleCheckRequestId: generateUUID(),
      parameterDependencyRuleCheckRequestId: generateUUID(),
      ruleCheckRequestId: generateUUID()
    }
  },
  computed: {
    resourceNameOptionList() {
      if (this.formData.slaveChipInterfaceTypeName) {
        return (
          this.formData.interfaceTypeOptionList.find(
            (item) => item.value == this.formData.slaveChipInterfaceTypeName
          )?.resourceNameOptionList ?? []
        )
      } else {
        return []
      }
    }
  },
  watch: {
    resourceNameOptionList: {
      handler(list) {
        let obj = list.find((item) => item.value == this.formData.masterChipResourceName)
        if (!obj?.value) {
          this.formData.masterChipResourceName = ''
          this.setPinAndParameterData({
            data: {
              parameterList: [],
              pinList: []
            }
          })
        }
      }
    },
    // 当项目id变化时，重新获取已使用的引脚编号列表
    '$attrs.project_data.projectId': {
      handler() {
        this.getUsedPinCodeList(1)
      }
    },
    'formData.masterChipResourceName': {
      handler() {
        this.getUsedPinCodeList(2)
      }
    }
  },
  mounted() {
    this.getUsedPinCodeList()
    receivedMessage(this.dataHandle)
  },
  methods: {
    dataHandle(result) {
      let self = this
      let e = defaultSettings.isWPF ? result : { data: JSON.parse(result) }
      if (e.data.webInfo.requestId === self.getPinAndParameterDataRequestId) {
        self.setPinAndParameterData(e.data.response)
      } else if (e.data.webInfo.requestId === self.getPinParameterRequestId) {
        self.setPinParameter(e.data.response)
      } else if (e.data.webInfo.requestId === self.getPinCodeOptionDataRequestId) {
        self.setPinCodeOptionData(e.data.response)
      } else if (e.data.webInfo.requestId === self.dependencyRuleCheckRequestId) {
        let res = e.data.response
        if (res.success) {
          self.currentRow.parameterList.forEach((item) => {
            item.show = res.data.matchConditionKeyList.includes(item.symbol)
          })
        } else {
          self.$message.error(res.message)
        }
      } else if (e.data.webInfo.requestId === self.parameterDependencyRuleCheckRequestId) {
        let res = e.data.response
        if (res.success) {
          self.parameterList.forEach((item) => {
            item.show = res.data.matchConditionKeyList.includes(item.symbol)
          })
        } else {
          self.$message.error(res.message)
        }
      } else if (e.data.webInfo.requestId === self.ruleCheckRequestId) {
        let res = e.data.response
        if (res.success) {
          self.handleRuleCheck(res)
        } else {
          self.$message.error(res.message)
        }
      } else if (e.data.webInfo.requestId === self.multipleDependencyRuleCheckRequestId) {
        let res = e.data.response
        if (res.success) {
          self.setPinAndParameterFields(e.data.response)
        } else {
          self.$notify.error(res.message)
        }
      }
    },
    is(row) {
      // console.log(row)
      this.dialogVisible = true
      let data = JSON.parse(JSON.stringify(row))
      let pinList = row.pinList ?? []
      pinList.forEach((item) => {
        data[item.masterChipPinName] = item.masterChipPinCode
      })
      this.parameterList = row.parameterList ?? []
      this.parameterList.forEach((item) => {
        // data[item.parameterName] = item.value
        data[item.symbol] = item.value
      })
      // console.log(row.masterChipResourceName)

      if (row.masterChipResourceName) {
        this.temPinList = pinList
        let params = { masterChipId: this.masterChipId, resourceName: row.masterChipResourceName }

        if (defaultSettings.isWPF || defaultSettings.isCEF) {
          this.getPinCodeOptionDataRequestId = generateUUID()
          let message = {
            RequestUrl: process.env.VUE_APP_URL + '/chipInterface/getPinCodeOptionData',
            RequestMethod: 'POST',
            Headers: {
              contentType: 'application/json'
            },
            QueryParameter: {},
            RequestBody: params,
            WebInfo: {
              requestId: this.getPinCodeOptionDataRequestId
            }
          }
          postMessage(message)
        } else {
          getPinCodeOptionData(params).then((res) => {
            this.setPinCodeOptionData(res)
          })
        }
      } else {
        this.pinList = pinList
      }
      this.formData = { ...data, masterChipResourceName: data.masterChipResourceName ?? '' }
      this.$nextTick(() => {
        this.$refs.formData.clearValidate()
      })
    },
    setPinCodeOptionData(res) {
      let pinObj = res.data
      this.pinList = this.temPinList.map((item) => {
        item.parameterList = item.parameterList ?? []
        item.parameterFormData = {}
        item.parameterList.forEach((row) => {
          this.$set(item.parameterFormData, row.symbol, row.value)
        })
        return {
          ...item,
          pinCodeOptionList: pinObj[item.masterChipPinName] ?? []
        }
      })
      this.setRules()
      let parameterFormData = {}
      this.parameterList.forEach((item) => {
        parameterFormData[item.symbol] = this.formData[item.symbol]
      })
      // console.log(this.parameterList, this.formData, parameterFormData)
      let params = {
        checkDataList: [
          {
            chipId: this.masterChipId,
            ruleSetType: 5,
            configDataList: this.pinList.map((pin) => {
              return {
                parameterData: pin.parameterFormData,
                objectId: pin.pinCodeOptionList.find((item) => item.value === this.formData[pin.masterChipPinName])
                  ?.pinId
              }
            })
          },
          {
            chipId: this.masterChipId,
            ruleSetType: 6,
            configDataList: [
              {
                parameterData: parameterFormData,
                objectId: this.resourceNameOptionList.find(
                  (item) => item.value === this.formData.masterChipResourceName
                )?.interfaceId
              }
            ]
          }
        ]
      }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.multipleDependencyRuleCheckRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/project/multipleDependencyRuleCheck',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: params,
          WebInfo: {
            requestId: this.multipleDependencyRuleCheckRequestId
          }
        }
        postMessage(message)
      } else {
        multipleDependencyRuleCheck(params).then((res) => {
          this.setPinAndParameterFields(res)
        })
      }
    },
    setPinAndParameterFields(res) {
      this.pinList.forEach((item, index) => {
        item.parameterList.forEach((row) => {
          this.$set(row, 'show', res.data[0].configDataList[index].matchConditionKeyList.includes(row.symbol))
        })
      })
      this.parameterList.forEach((item) => {
        this.$set(item, 'show', res.data[1].configDataList[0].matchConditionKeyList.includes(item.symbol))
      })
    },
    // 获取已使用的引脚编号列表
    getUsedPinCodeList(flag) {
      if (flag == 1) {
        let project_configData = this.$attrs.project_data
        // 设置已使用的引脚编号列表为空
        this.usedPinCodeList = []
        let nodeList = project_configData.layoutContent.content.edges
        this.usedPinCodeList = nodeList.flatMap((node) =>
          node.data.configData.interfaceList.flatMap((interfaceInfo) =>
            (interfaceInfo.pinList || []).map((pin) => pin.masterChipPinCode)
          )
        )
      } else if (flag == 2) {
        // 清空已使用的引脚编号列表
        this.usedPinCodeList = []
        let this_projectConfigData = this.$parent.getChartData().content.edges
        if (this_projectConfigData != undefined) {
          // 遍历每一项配置获取引脚编号
          this_projectConfigData.forEach((edge) => {
            // 如果edge.id和this.$attrs.edge_id相同，跳过
            if (edge.id == this.$attrs.edge_id) {
              return
            }
            edge.data.configData.interfaceList.forEach((interfaceInfo) => {
              ;(interfaceInfo.pinList || []).forEach((pin) => {
                this.usedPinCodeList.push(pin.masterChipPinCode)
              })
            })
          })
        }
        let this_configData = this.$attrs.config_data
        if (this_configData.length > 0) {
          // 遍历每一项配置获取引脚编号
          this_configData.forEach((interfaceInfo) => {
            // 如果interfaceInfo.slaveChipControlModeInterfaceId和this.formData.slaveChipControlModeInterfaceId相同，跳过
            if (interfaceInfo.slaveChipControlModeInterfaceId == this.formData.slaveChipControlModeInterfaceId) {
              return
            }
            // 如果interfaceInfo.pinList不为空
            if (interfaceInfo.pinList != undefined) {
              interfaceInfo.pinList.forEach((pin) => {
                this.usedPinCodeList.push(pin.masterChipPinCode)
              })
            }
          })
        }
      }
    },
    // 引脚配置字段显隐
    getRealPinList(pin) {
      this.currentRow = pin
      let params = {
        chipId: this.masterChipId,
        ruleSetType: 5,
        parameterData: pin.parameterFormData,
        objectId: pin.pinCodeOptionList.find((item) => item.value === this.formData[pin.masterChipPinName])?.pinId
      }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.dependencyRuleCheckRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/project/dependencyRuleCheck',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: params,
          WebInfo: {
            requestId: this.dependencyRuleCheckRequestId
          }
        }
        postMessage(message)
      } else {
        dependencyRuleCheck(params).then((res) => {
          pin.parameterList.forEach((item) => {
            item.show = res.data.matchConditionKeyList.includes(item.symbol)
          })
        })
      }
    },
    // 参数配置字段显隐
    getRealParameterList() {
      let parameterFormData = {}
      this.parameterList.forEach((item) => {
        if (item.show) {
          parameterFormData[item.symbol] = this.formData[item.symbol]
        }
      })
      let params = {
        chipId: this.masterChipId,
        ruleSetType: 6,
        parameterData: parameterFormData,
        objectId: this.resourceNameOptionList.find((item) => item.value === this.formData.masterChipResourceName)
          ?.interfaceId
      }
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.parameterDependencyRuleCheckRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/project/dependencyRuleCheck',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: params,
          WebInfo: {
            requestId: this.parameterDependencyRuleCheckRequestId
          }
        }
        postMessage(message)
      } else {
        dependencyRuleCheck(params).then((res) => {
          this.parameterList.forEach((item) => {
            item.show = res.data.matchConditionKeyList.includes(item.symbol)
          })
        })
      }
    },
    handleClose() {
      this.parameterList = []
      this.pinList = []
    },
    getStrLength(str) {
      return getStrLength(str)
    },
    setRules() {
      let rules = {
        slaveChipInterfaceTypeName: [{ required: true, message: '请选择接口类型', trigger: ['blur', 'change'] }],
        masterChipResourceName: [{ required: true, message: '请选择资源', trigger: ['blur', 'change'] }]
      }
      const setRules = (fields, rules) => {
        fields.forEach((item) => {
          if (item.dataType === 'enum' || item.validValues?.split(',')?.length > 1) {
            rules[item.symbol] = [
              { required: true, message: '请选择' + item.parameterName, trigger: ['blur', 'change'] }
            ]
          } else if (['integer', 'float'].includes(item.dataType)) {
            rules[item.symbol] = [{ required: true, message: '请输入' + item.parameterName, trigger: 'blur' }]
          }
        })
      }
      this.pinList.forEach((item) => {
        item.rules = {}
        setRules(item.parameterList, item.rules)
        rules[item.masterChipPinName] = [
          { required: true, message: '请选择' + item.masterChipPinName, trigger: ['blur', 'change'] }
        ]
      })
      setRules(this.parameterList, rules)
      this.rules = rules
      this.$nextTick(() => {
        this.$refs.formData.clearValidate()
        this.$refs.pinForm?.forEach((item) => {
          item.clearValidate()
        })
      })
    },
    handleChange(val) {
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.getPinAndParameterDataRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/chipInterface/getPinAndParameterData',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: { masterChipId: this.masterChipId, resourceName: val },
          WebInfo: {
            requestId: this.getPinAndParameterDataRequestId
          }
        }
        postMessage(message)
      } else {
        getPinAndParameterData({ masterChipId: this.masterChipId, resourceName: val }).then((res) => {
          this.setPinAndParameterData(res)
        })
      }
    },
    setPinAndParameterData(res) {
      this.parameterList = res.data.parameterList.map((item) => {
        return {
          ...item,
          show: true
        }
      })
      res.data.parameterList.forEach((item) => {
        this.$set(this.formData, item.parameterName, ['integer', 'float'].includes(item.dataType) ? undefined : '')
      })
      res.data.pinList.forEach((item) => {
        this.$set(item, 'show', true)
        this.$set(item, 'parameterList', [])
        this.$set(item, 'parameterFormData', {})
        this.$set(this.formData, item.masterChipPinName, '')
      })
      this.pinList = res.data.pinList
      this.setRules()
    },
    handleChangePin(val, row) {
      let params = {
        resourceName: this.formData.masterChipResourceName,
        pinName: row.masterChipPinName,
        pinCode: val,
        masterChipId: this.masterChipId
      }
      this.currentRow = row
      if (defaultSettings.isWPF || defaultSettings.isCEF) {
        this.getPinParameterRequestId = generateUUID()
        let message = {
          RequestUrl: process.env.VUE_APP_URL + '/chipPinParameter/getList',
          RequestMethod: 'POST',
          Headers: {
            contentType: 'application/json'
          },
          QueryParameter: {},
          RequestBody: params,
          WebInfo: {
            requestId: this.getPinParameterRequestId
          }
        }
        postMessage(message)
      } else {
        getPinParameter(params).then((res) => {
          this.setPinParameter(res)
        })
      }
    },
    setPinParameter(res) {
      this.currentRow.parameterList = res.data.map((item) => {
        return { ...item, show: false }
      })
      this.currentRow.parameterFormData = {}
      this.currentRow.parameterList.forEach((item) => {
        // row.parameterFormData[item.symbol] = ['integer', 'float'].includes(item.dataType) ? undefined : ''
        this.$set(
          this.currentRow.parameterFormData,
          item.symbol,
          ['boolean'].includes(item.dataType)
            ? item.defaultValue === 'false'
              ? false
              : Boolean(item.defaultValue)
            : item.defaultValue ?? undefined
        )
      })
      this.setRules()
      this.getRealPinList(this.currentRow)
    },
    handelConfirm() {
      this.setRules()
      this.$nextTick(() => {
        this.$refs.formData.validate((valid) => {
          if (valid) {
            let result = true
            this.$refs.pinForm?.forEach((item) => {
              item.validate((valid) => {
                result = result && valid
              })
            })
            if (!result) return
            let parameterFormData = {}
            this.parameterList.forEach((item) => {
              if (item.show) {
                parameterFormData[item.symbol] = this.formData[item.symbol]
              }
            })
            let params = {
              checkDataList: [
                {
                  chipId: this.masterChipId,
                  ruleSetType: 5,
                  configDataList: this.pinList.map((pin) => {
                    let obj = {}
                    pin.parameterList.forEach((item) => {
                      item.show && (obj[item.symbol] = pin.parameterFormData[item.symbol])
                    })
                    return {
                      parameterData: obj,
                      objectId: pin.pinCodeOptionList.find(
                        (item) => item.value === this.formData[pin.masterChipPinName]
                      )?.pinId
                    }
                  })
                },
                {
                  chipId: this.masterChipId,
                  ruleSetType: 6,
                  configDataList: [
                    {
                      parameterData: parameterFormData,
                      objectId: this.resourceNameOptionList.find(
                        (item) => item.value === this.formData.masterChipResourceName
                      )?.interfaceId
                    }
                  ]
                }
              ]
            }
            if (defaultSettings.isWPF || defaultSettings.isCEF) {
              this.ruleCheckRequestId = generateUUID()
              let message = {
                RequestUrl: process.env.VUE_APP_URL + '/project/ruleCheck',
                RequestMethod: 'POST',
                Headers: {
                  contentType: 'application/json'
                },
                QueryParameter: {},
                RequestBody: params,
                WebInfo: {
                  requestId: this.ruleCheckRequestId
                }
              }
              postMessage(message)
            } else {
              ruleCheck(params).then((res) => {
                this.handleRuleCheck(res)
              })
            }
          }
        })
      })
    },
    handelCancle() {
      this.dialogVisible = false
    },
    handleRuleCheck(res) {
      const setRules = (fields, rules, notMatchConditionKeyList) => {
        fields.forEach((item) => {
          if (notMatchConditionKeyList.includes(item.symbol)) {
            rules[item.symbol] || (rules[item.symbol] = [])
            rules[item.symbol].push({
              validator: (rule, value, callback) => {
                let validValues = item.validValues
                if (validValues && validValues.indexOf('~') !== -1) {
                  let arr = validValues.split('~')
                  let min = Number(arr[0])
                  let max = Number(arr[1])
                  if (value < min || value > max) {
                    callback(new Error(item.parameterName + '参数配置超出有效值范围'))
                  } else {
                    callback()
                  }
                } else {
                  callback(new Error(item.parameterName + '参数配置超出有效值范围'))
                }
              },
              trigger: ['blur', 'change']
            })
          }
        })
      }
      let result = true
      this.pinList.forEach((item, index) => {
        setRules(item.parameterList, item.rules, res.data[0].configDataList[index].notMatchConditionKeyList)
      })
      setRules(this.parameterList, this.rules, res.data[1].configDataList[0].notMatchConditionKeyList)
      this.$nextTick(() => {
        this.$refs.pinForm?.forEach((item) => {
          item.validate((valid) => {
            result = result && valid
          })
        })
        if (!result) return
        this.$refs.formData.validate((valid) => {
          if (valid) {
            this.dialogVisible = false
            this.$emit('saveInterfaceSetting', {
              slaveChipInterfaceTypeName: this.formData.slaveChipInterfaceTypeName,
              slaveChipInterfaceDescription: this.formData.slaveChipInterfaceDescription,
              slaveChipControlModeInterfaceId: this.formData.slaveChipControlModeInterfaceId,
              slaveChipInterfaceName: this.formData.slaveChipInterfaceName,
              slaveChipInterfaceType: this.formData.slaveChipInterfaceType,
              masterChipResourceName: this.formData.masterChipResourceName,
              interfaceTypeOptionList: this.formData.interfaceTypeOptionList,
              parameterList: this.parameterList.map((item) => {
                return {
                  ...item,
                  value: item.show ? this.formData[item.symbol] : undefined
                }
              }),
              pinList: this.pinList.map((item) => {
                return {
                  ...item,
                  masterChipPinCode: this.formData[item.masterChipPinName],
                  parameterList: item.parameterList.map((row) => {
                    row.value = row.show ? item.parameterFormData[row.symbol] : undefined
                    return row
                  })
                }
              })
            })
          }
        })
      })
    },
    // 判断引脚编号是否已被使用
    isDisabled(value) {
      return this.usedPinCodeList.includes(value)
    }
  }
}
</script>

<style lang="less" scoped>
.myForm {
  max-height: 500px;
  overflow-y: auto;
  overflow-x: hidden;
  .w100 {
    width: 100%;
  }
  .mySelect {
    width: 150px;
  }

  .label-position-right {
    /deep/.el-form-item__label {
      float: left;
      text-align: right;
    }
    /deep/.el-form-item__error {
      margin-left: 53px;
    }
  }
  .label-position-right1 {
    /deep/.el-form-item__label {
      float: left;
      text-align: right;
    }
    /deep/.el-form-item__error {
      margin-left: 80px;
    }
  }

  .title .el-divider__text {
    font-size: 15px;
    font-weight: 600;
  }
  .interfaceType {
    width: 174px;
    display: inline-block;
  }
  .pinBox {
    border: 1px solid #ddd;
    padding: 15px 15px 5px;
    margin-bottom: 10px;
    border-radius: 3px;
  }
}
</style>
